﻿using System;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.NetworkInformation;

namespace EventScavenger
{
    [Flags]
    enum Internet_ConnectionState : int
    {
        INTERNET_CONNECTION_MODEM = 0x1,
        INTERNET_CONNECTION_LAN = 0x2,
        INTERNET_CONNECTION_PROXY = 0x4,
        INTERNET_RAS_INSTALLED = 0x10,
        INTERNET_CONNECTION_OFFLINE = 0x20,
        INTERNET_CONNECTION_CONFIGURED = 0x40
    }

    public static class PingHelper
    {
        [DllImport("wininet", CharSet = CharSet.Auto)]
        static extern bool InternetGetConnectedState(ref Internet_ConnectionState lpdwFlags, int dwReserved);

        /// <summary>
        /// Get local machine network status
        /// </summary>
        /// <returns>True if network is up</returns>
        public static bool IsOffline()
        {
            Internet_ConnectionState state = 0;
            InternetGetConnectedState(ref state, 0);
            if (((int)Internet_ConnectionState.INTERNET_CONNECTION_OFFLINE & (int)state) != 0)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Check if the host is pingable
        /// </summary>
        /// <param name="host">Name or ip of host</param>
        /// <returns>True on success</returns>
        public static bool CanPingHost(string host)
        {
            bool success = false;
            try
            {
                IPAddress ip = null;
                ip = Dns.GetHostEntry(host).AddressList[0]; //must have at least 1 ip address

                //set options ttl=128 and no fragmentation
                PingOptions options = new PingOptions(128, true);

                //create a Ping object
                Ping ping = new Ping();
                byte[] data = new byte[32];
                //send the ping request
                PingReply reply = ping.Send(ip, 1000, data, options);
                if (reply != null)
                {
                    switch (reply.Status)
                    {
                        case IPStatus.Success:
                            success = true;
                            break;
                        case IPStatus.TimedOut:
                            success = false;
                            break;
                        default:
                            //Console.WriteLine("Ping failed {0}", reply.Status.ToString());
                            success = false;
                            break;
                    }
                }
                else
                {
                    success = false;
                    //Console.WriteLine("Ping failed for an unknown reason");
                }

            }
            catch (Exception)
            {
                success = false;
            }
            return success;
        }

        /// <summary>
        /// Get more details about why a ping to the host fails
        /// </summary>
        /// <param name="host">Name or ip of host</param>
        /// <returns>Reason of failure, blank on no error</returns>
        public static string GetPingHostErrorReason(string host)
        {
            string result = "";
            try
            {
                IPAddress ip = null;
                ip = Dns.GetHostEntry(host).AddressList[0]; //must have at least 1 ip address

                //set options ttl=128 and no fragmentation
                PingOptions options = new PingOptions(128, true);

                //create a Ping object
                Ping ping = new Ping();
                byte[] data = new byte[32];
                //send the ping request
                PingReply reply = ping.Send(ip, 1000, data, options);
                if (reply != null)
                {
                    switch (reply.Status)
                    {
                        case IPStatus.Success:
                            result = "";
                            break;
                        case IPStatus.TimedOut:
                            result = "Timeout";
                            break;
                        default:
                            result = "Ping failed " + reply.Status.ToString();
                            break;
                    }
                }
                else
                {
                    result = "Ping failed for an unknown reason";
                }

            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            return result;
        }
    }
}
